package com.itheima.cs.utils;

import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Vector;

public class EscCommand {


    public static final byte INIT[] = {(byte) 0x1B, (byte) 0x40};

    public static final byte[] ESC_ALIGN_LEFT = {0x1B, 0x61, 0x00};
    public static final byte[] ESC_ALIGN_CENTER = {0x1B, 0x61, 0x01};
    public static final byte[] ESC_ALIGN_RIGHT = {0x1B, 0x61, 0x02};


    public static final byte BK[] = {(byte) 0x1B, (byte) 0x57, (byte) 0x1};

    public static final byte UBK[] = {(byte) 0x1B, (byte) 0x57, (byte) 0x0};


    public static final byte BG[] = {(byte) 0x1C, (byte) 0x21, (byte) 0x8};

    public static final byte UBG[] = {(byte) 0x1C, (byte) 0x21, (byte) 0x0};


    public static final byte BGK[] = {(byte) 0x1C, (byte) 0x57, (byte) 0x1};

    public static final byte UBGK[] = {(byte) 0x1C, (byte) 0x57, (byte) 0x0};


    public static final byte CT[] = {(byte) 0x1B, (byte) 0x45};

    public static final byte UCT[] = {(byte) 0x1B, (byte) 0x46};


    public static final byte HH[] = {(byte) 0x0D, (byte) 0x0A};


    public static final byte[] FEED_PAPER_AND_CUT = {0x1D, 0x56, 0x42, 0x00};


    public static final byte FB[] = {(byte) 0x1B, (byte) 0x6A, (byte) 0};

    private ByteBuffer data;

    public EscCommand() {
        data =  ByteBuffer.allocate(1024*10);
        addInitializePrinter();
    }

    private void addArrayToCommand(byte[] array) {
        data.put(array);
    }

    public byte[] getData(){
        byte[] b = new byte[data.position()];
        data.flip();
        data.get(b);
        return b;
    }

    public void addInitializePrinter() {
        byte[] command = new byte[]{27, 64};
        this.addArrayToCommand(command);
    }


    public void addPrintAndFeedLines(byte n) {
        byte[] command = new byte[]{0x1B, 0x64, n};
        this.addArrayToCommand(command);
    }

    public void addSelectAlign(Align align) {
        byte[] command = new byte[]{27, 97, align.getValue()};
        this.addArrayToCommand(command);
    }

    public void addSelectPrintModes(boolean isBold, /*boolean isEmphasized,*/ boolean isDoubleHeight, boolean isDoubleWidth, boolean isUnderline, boolean isItalic ) {
        this.addArrayToCommand(isBold?new byte[]{27,69}:new byte[]{27,70});



        this.addArrayToCommand(isItalic?new byte[]{27,52}:new byte[]{27,53});



        byte temp = 0;
        if (isDoubleWidth) {
            temp = 4;
        }

        if (isDoubleHeight) {
            temp = (byte)(temp | 8);
        }

        if (isUnderline) {
            temp = (byte)(temp | 128);
        }
        this.addArrayToCommand(new byte[]{28,33, temp});
    }


    public void addHorDrawLine(double lenght, boolean isBold) {
        String str = "─";
        if(isBold){
            str = "━";
        }
        this.addArrayToCommand(new byte[]{28, 118, 1});

        int count = (int) Math.ceil(lenght / 3.9);
        for (int i = 0; i < count; i++) {
            if(isBold){
                str += "━";
            } else {
                str += "─";
            }
        }
        this.addStrToCommand(str);
        this.addArrayToCommand(new byte[]{28, 118, 0});
    }


    public void addVerDrawLine(double lenght, boolean isBold) {
        String str = "│\n";
        if(isBold){
            str = "┃\n";
        }
        this.addArrayToCommand(new byte[]{28, 118, 1});

        int count = (int) Math.ceil(lenght / 3.9);
        for (int i = 0; i < count; i++) {
            if(isBold){
                str += "┃\n";
            } else {
                str += "│\n";
            }
        }
        this.addStrToCommand(str);
        this.addArrayToCommand(new byte[]{28, 118, 0});
    }


    public void addSetMoveUnits(int value) {
        byte[] command = new byte[]{0x1B, 0x28, 0x55, 0x01, 0x00, (byte) value};
        this.addArrayToCommand(command);
    }


    public void addSetPaperHeight(double value) {
        int temp = (int) (value * 1800 / 127);
        int n1 = temp%255;
        int n2 = temp/255;

        byte[] command = new byte[]{27, 40, 67,2,0, (byte) n1, (byte) n2};
        this.addArrayToCommand(command);
    }


    public void addPaddingLeft(byte value) {
        byte[] command = new byte[]{27, 108, value};
        this.addArrayToCommand(command);
    }


    public void addPaddingRight(byte value) {
        byte[] command = new byte[]{27, 81, value};
        this.addArrayToCommand(command);
    }


    public void addSetHorAbsolutePrintPosition(int value) {
        byte[] command = new byte[]{0x1B, 0x24, 0, 0};

        int temp = (int) (value * 360 / 25.4);
        int n1 = temp%256;
        int n2 = temp/256;
        command[2] = (byte) n1;
        command[3] = (byte) n2;
        this.addArrayToCommand(command);
    }


    public void addSetHorRelativePrintPosition(int value) {
        byte[] command = new byte[]{0x1B, 0x5C, 0, 0};

        int temp = (int) (value * 360 / 25.4);
        int n1 = temp%256;
        int n2 = temp/256;

        command[2] = (byte) n1;
        command[3] = (byte) n2;
        this.addArrayToCommand(command);
    }


    public void addSetVerAbsolutePrintPosition(int value) {
        byte[] command = new byte[]{0x1B, 0x28, 0x56, 0x02, 0x00, 0, 0};

        int temp = (int) (value * 180 / 25.4);
        int n1 = temp%256;
        int n2 = temp/256;
        command[5] = (byte) n1;
        command[6] = (byte) n2;
        this.addArrayToCommand(command);
    }


    public void addSetVerRelativePrintPosition(int value) {
        byte[] command = new byte[]{0x1B, 0x28, 0x76, 0x02, 0x00, 0, 0};

        int temp = (int) (Math.abs(value) * 180 / 25.4);
        int n1 = temp%256;
        int n2 = temp/256;

        if(value >= 0){
            command[5] = (byte)n1;
        } else {
            n2 = (65536-temp)/256;
            command[5] = (byte) ((65536-temp)-n2*256);
        }
        command[6] = (byte)n2;
        this.addArrayToCommand(command);
    }


    public void addFeedPaper(double value) {
        int n = (int) (Math.abs(value) * 180 /25.4);
        byte[] command = new byte[]{0x1B, 0x4A, (byte) n};
        if(value < 0){
            command = new byte[]{0x1B, 0x6A, (byte) n};
        }
        this.addArrayToCommand(command);
    }

    public void addText(String text) {
        this.addStrToCommand(text);
    }

    public void addText(String text, String charsetName) {
        this.addStrToCommand(text, charsetName);
    }


    public void addSetBarcodeHeight(byte height) {
        byte[] command = new byte[]{0X1D, 0X68, height};
        this.addArrayToCommand(command);
    }

    public void addSetBarcodeWidth(byte width) {
        byte[] command = new byte[]{0x1D,0x77, 0X02};
        if (width > 6) {
            width = 6;
        }

        if (width < 2) {
            width = 2;
        }
        command[2] = width;
        this.addArrayToCommand(command);
    }


    public void addPrintBarCode(String content, byte position) {

        byte[] data = stringToByte(content);
        byte[] command = new byte[]{0x1D, 0x1B, 0x49, (byte)data.length};
        this.addArrayToCommand(command);
        this.addArrayToCommand(data);
    }

    public void addPrintQrCodeData(String content) {
        byte[] text = content.getBytes();
        byte[] len = intToByte2(text.length + 3);

        byte[] first = new byte[]{0x1D, 0x28, 0x6B, 0x04, 0x00, 0x31, 0x41, 0x32, 0x00,
                0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x43, 0x03,
                0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x45, 0x30,
                0x1D, 0x28, 0x6B, len[0], len[1], 0x31, 0x50, 0x30};

        byte[] end = new byte[]{0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x51, 0x30};

        byte[] data = new byte[first.length + text.length + end.length];

        System.arraycopy(first, 0, data, 0, first.length);
        System.arraycopy(text, 0, data, first.length, text.length);
        System.arraycopy(end, 0, data, first.length + text.length, end.length);
        this.addArrayToCommand(data);
    }


    public void addPrintAndLineFeed() {
        byte[] command = new byte[]{10};
        this.addArrayToCommand(command);
    }



    public void addFeedPaperHeight() {
        byte[] command = new byte[]{0x0C};
        this.addArrayToCommand(command);
    }

    private void addStrToCommand(String str) {
        byte[] bs = stringToByte(str);
        addArrayToCommand(bs);
    }

    private void addStrToCommand(String str, String charset) {
        byte[] bs = null;
        if (!str.equals("")) {
            try {
                bs = str.getBytes(charset);
                addArrayToCommand(bs);
            } catch (UnsupportedEncodingException var5) {
                var5.printStackTrace();
            }
        }
    }

    public static byte[] stringToByte(String str){
        if(TextUtils.isEmpty(str)){
            return new byte[0];
        }
        try {
            byte[] data = str.getBytes("GB18030");
            return data;
        } catch (UnsupportedEncodingException var4) {
            return new byte[0];
        }
    }

    private static byte[] intToByte2(int i) {
        byte[] targets = new byte[2];
        targets[1] = (byte) (i >> 8 & 0xFF);
        targets[0] = (byte) (i & 0xFF);
        return targets;
    }

    public static enum Align {
        LEFT(0),
        CENTER(1),
        RIGHT(2);

        private final int value;

        private Align(int value) {
            this.value = value;
        }

        public byte getValue() {
            return (byte)this.value;
        }
    }

    public static enum FONT {
        FONTA(0),
        FONTB(1);

        private final int value;

        private FONT(int value) {
            this.value = value;
        }

        public byte getValue() {
            return (byte)this.value;
        }
    }


    public static byte[] test(){
        EscCommand escCommand = new EscCommand();
        escCommand.addSetMoveUnits(10);
        escCommand.addText("第一个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第二个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第三个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第四个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第五个");

        escCommand.addPrintAndLineFeed();
        escCommand.addText("第二个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第三个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第四个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第五个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第六个");

        escCommand.addSetVerAbsolutePrintPosition(80);
        escCommand.addText("第七个");

        escCommand.addSetVerAbsolutePrintPosition(120);
        escCommand.addText("第八个");

        escCommand.addFeedPaper(10);
        escCommand.addText("第九个");

        escCommand.addPrintAndLineFeed();

        escCommand.addText("第一个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第二个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第三个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第四个");
        escCommand.addSetHorRelativePrintPosition(20);
        escCommand.addText("第五个");

        escCommand.addPrintAndLineFeed();
        escCommand.addSetVerAbsolutePrintPosition(60);
        escCommand.addText("哈哈哈哈哈哈哈哈哈哈");

        escCommand.addFeedPaper(-10);
        escCommand.addText("ooooooooooooooooooooooooooooooooooooooooooooo");
        escCommand.addSetHorAbsolutePrintPosition(0);
        escCommand.addFeedPaper(-10);
        escCommand.addText("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq");
        escCommand.addText("\r\n\r\n\r\n");
        return escCommand.getData();
    }
}
